package ma.xin.shi.arxml.comm;

import java.util.ArrayList;
import java.util.List;
//import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XmlParseComm {
	/**
	 * 获取元素的标签名
	 * @param element 目标元素
	 * @return 元素的标签名（区分大小写），若element为null则返回null
	 */
	public static String getElementTagName(Element element) {
	    if (element == null) {
	        return null;
	    }
	    // 返回元素的标签名
	    return element.getTagName();
	}
	
	/**
	* 获取指定元素节点的文本内容。
	* 注意：此方法直接获取该元素本身包含的所有文本内容（包括其所有后代节点的文本），
	* 并返回去除首尾空白字符后的结果。
	* @param node 要获取文本内容的元素节点（不能为 null，否则可能抛出空指针异常）
	* @return 元素的文本内容；若元素无文本内容（或仅包含空白字符），则返回空字符串处理后的 null
	*/
	public static String getNodeText(Element node) {
		String text = null;

		text = node.getTextContent().trim();

		return text;
	}
	
	/**
	 * 提取指定父元素下**所有层级中**第一个匹配标签名的元素的文本内容。
	 * 注意：此方法会递归查找父元素下的所有后代元素（包括子元素、孙元素等），
	 * 并返回第一个匹配标签名的元素的文本内容（自动去除首尾空白字符）。
	 * 
	 * @param parent  父元素节点，作为查找的起点（不能为null，否则可能抛出空指针异常）
	 * @param tagName 要查找的元素标签名（区分大小写，不能为null或空字符串）
	 * @return 匹配标签的文本内容；若未找到匹配元素，或元素无文本内容，则返回null
	 */
    public static String getTextContent(Element parent, String tagName) {
        NodeList list = parent.getElementsByTagName(tagName);
        if (list.getLength() > 0) {
            return list.item(0).getTextContent().trim();
        }
        return null;
    }

    /**
     * 提取指定父元素下**第一层子节点中**第一个匹配标签名的元素的文本内容。
     * 注意：此方法仅查找父元素的直接子元素（不包括孙元素等更深层次的后代），
     * 并返回第一个匹配标签名的元素的文本内容（自动去除首尾空白字符）。
     * 
     * @param parent  父元素节点，作为查找的起点（不能为null，否则可能抛出空指针异常）
     * @param tagName 要查找的元素标签名（区分大小写，不能为null或空字符串）
     * @return 匹配标签的文本内容；若未找到匹配元素，或元素无文本内容，则返回null
     */
    public static String getDirectChildTextContent(Element parent, String tagName) {
        // 获取父元素的所有直接子节点
        NodeList childNodes = parent.getChildNodes();
        
        // 遍历所有直接子节点
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            // 检查节点是否为元素节点且标签名匹配
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) node;
                if (tagName.equals(childElement.getTagName())) {
                    // 获取文本内容并去除首尾空白
                    String textContent = childElement.getTextContent();
                    return textContent != null ? textContent.trim() : null;
                }
            }
        }
        
        // 未找到匹配的直接子元素
        return null;
    }
    
    /**
     * 获取指定父元素下**所有层级中**第一个匹配标签名的子元素。
     * 注意：此方法会递归查找父元素下的所有后代元素（包括子元素、孙元素等），
     * 并返回第一个匹配标签名的元素节点。
     * 
     * @param parent  父元素节点，作为查找的起点（不能为null，否则可能抛出空指针异常）
     * @param tagName 要查找的元素标签名（区分大小写，不能为null或空字符串）
     * @return 第一个匹配标签名的元素；若未找到匹配元素，则返回null
     */
    public static Element getFirstChildElement(Element parent, String tagName) {
        NodeList list = parent.getElementsByTagName(tagName);
        if (list.getLength() > 0) {
            return (Element) list.item(0);
        }
        return null;
    }
    
    /**
     * 获取指定父元素下**第一层子节点中**第一个匹配标签名的元素。
     * 注意：此方法仅查找父元素的直接子元素（不包括孙元素等更深层次的后代），
     * 并返回第一个匹配标签名的元素节点。
     * 
     * @param parent  父元素节点，作为查找的起点（不能为null，否则可能抛出空指针异常）
     * @param tagName 要查找的元素标签名（区分大小写，不能为null或空字符串）
     * @return 第一个匹配标签名的直接子元素；若未找到匹配元素，则返回null
     */
    public static Element getFirstDirectChildElement(Element parent, String tagName) {
        if (null == parent) {
        	logEx("parent is null");
        	return null;
        }
    	
    	// 获取父元素的所有直接子节点
        NodeList childNodes = parent.getChildNodes();
        
        // 遍历所有直接子节点
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            // 检查节点是否为元素节点且标签名匹配
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) node;
                if (tagName.equals(childElement.getTagName())) {
                    return childElement;
                }
            }
        }
        
        logEx("在节点：" +parent.getTagName() + "中未找到： " +tagName);
        // 未找到匹配的直接子元素
        return null;
    }

    /**
     * 打印日志或调试信息
     */
    public static void log(String message) {
        System.out.println("[ARXML Parser] " + message);
    }

    private static final boolean ENABLE_CALLER_INFO = true; // 调试时开启
    public static void logEx(String message) {
        String callerInfo = "";
        if (ENABLE_CALLER_INFO) {
            StackTraceElement caller = Thread.currentThread().getStackTrace()[2];
            String simpleName = caller.getClassName();
            simpleName = simpleName.substring(simpleName.lastIndexOf('.') + 1);
            callerInfo = String.format("[%s.%s:%d] ", simpleName, caller.getMethodName(), caller.getLineNumber());
        }
        System.out.println("[ARXML Parser] " + callerInfo + message);
    }

    /**
     * 获取packageElement直接子节点中<Node>标签的值
     * @param packageElement 要解析的AR-PACKAGE元素
     * @return Node标签的值，如果未找到则返回null
     */
    public static String getDirectNodeValue(Element packageElement, String Node) {
        // 获取所有直接子节点
        NodeList childNodes = packageElement.getChildNodes();

        // 遍历所有直接子节点
        for (int i = 0; i < childNodes.getLength(); i++) {
            // 只处理元素节点
            if (childNodes.item(i) instanceof Element) {
                Element childElement = (Element) childNodes.item(i);
                
                // 检查是否是Node标签
                if (Node.equals(childElement.getTagName())) {
                    // 返回标签内的文本内容
                    return childElement.getTextContent().trim();
                }
            }
        }

        // 未找到 <Node> 标签
        return null;
    }

    /**
     * 获取packageElement直接子节点中<SHORT-NAME>标签的值
     * @param packageElement 要解析的AR-PACKAGE元素
     * @return SHORT-NAME标签的值，如果未找到则返回null
     */
    public static String getDirectShortName(Element packageElement) {
        // 获取所有直接子节点
        NodeList childNodes = packageElement.getChildNodes();

        // 遍历所有直接子节点
        for (int i = 0; i < childNodes.getLength(); i++) {
            // 只处理元素节点
            if (childNodes.item(i) instanceof Element) {
                Element childElement = (Element) childNodes.item(i);
                
                // 检查是否是SHORT-NAME标签
                if ("SHORT-NAME".equals(childElement.getTagName())) {
                    // 返回标签内的文本内容
                    return childElement.getTextContent().trim();
                }
            }
        }

        // 未找到SHORT-NAME标签
        return null;
    }

    /**
     * 获取指定节点的所有一级子元素节点（仅元素节点，非递归）
     * @param parentElement 父节点
     * @return 一级子元素列表（空列表表示无符合条件的子节点）
     */
    public static List<Element> getDirectChildElements(Element parentElement) {
        List<Element> childElements = new ArrayList<>();
        if (parentElement == null) {
            log("[File]XmlParseComm,[Fun]getDirectChildElements, 父节点为null，无法获取子节点");
            return childElements;
        }

        // 获取所有直接子节点（包括文本、注释等非元素节点）
        NodeList childNodes = parentElement.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            // 仅保留元素节点（过滤文本、注释、空白节点等）
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                childElements.add((Element) node);
            }
        }

        return childElements;
    }

    /**
     * 获取指定父节点下所有的一级子元素节点（仅直接子元素，非递归）
     * 仅返回元素节点，不包含文本节点、注释节点等非元素类型节点
     * 不包含任何后代节点（孙节点及以下层级）
     * 
     * @param parentElement 父节点，作为查找的起点
     * @return 所有一级子元素节点列表，若没有子元素则返回空列表（永远不为null）
     * @ 此方法等于 getDirectChildElements
     */
    public static List<Element> getAllDirectChildElements(Element parentElement) {
        List<Element> directChildElements = new ArrayList<>();

        // 处理父节点为null的情况
        if (parentElement == null) {
            logEx("父节点为null，无法获取子节点");
            return directChildElements;
        }

        // 获取所有直接子节点并筛选元素节点
        NodeList childNodes = parentElement.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            // 仅处理元素节点
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) node;
                directChildElements.add(childElement);
            }
        }

        logEx("在父节点下找到 " + directChildElements.size() + " 个一级子元素节点");
        return directChildElements;
    }

    /**
     * 获取指定父节点下所有标签名为指定值的一级子元素节点（仅直接子元素，非递归）
     * 仅返回标签名完全匹配的元素节点，不包含任何后代节点（孙节点及以下层级）
     * 
     * @param parentElement 父节点，作为查找的起点
     * @param targetTagName 目标标签名（区分大小写，如"AR-PACKAGE"）
     * @return 匹配标签名的一级子元素列表，若没有匹配项则返回空列表（永远不为null）
     */
    public static List<Element> getDirectChildElementsByTagName(Element parentElement, String targetTagName) {
        List<Element> matchedElements = new ArrayList<>();

        // 处理父节点为null的情况
        if (parentElement == null) {
            logEx("父节点为null，无法获取子节点");
            return matchedElements;
        }

        // 处理目标标签名为null或空字符串的情况
        if (targetTagName == null || targetTagName.trim().isEmpty()) {
        	logEx("目标标签名不能为空");
            return matchedElements;
        }
        String trimmedTagName = targetTagName.trim();

        // 获取所有直接子节点并筛选
        NodeList childNodes = parentElement.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            // 仅处理元素节点且标签名匹配的情况
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) node;
                if (trimmedTagName.equals(childElement.getTagName())) {
                    matchedElements.add(childElement);
                }
            }
        }

        logEx("在父节点下找到 " + matchedElements.size() + " 个标签为[" + trimmedTagName + "]的一级子元素");
        return matchedElements;
    }

    /**
     * 获取指定父节点下所有标签名为指定值的直接子节点列表，忽略子节点内部结构
     * 无论子节点内部包含多少复杂元素，只要标签名匹配且是直接子节点就会被返回
     * 
     * @param parentNode 父节点，作为查找的起点（可以是任何Element节点）
     * @param parentTagName 父节点的标签名（用于日志和校验，增强代码可读性）
     * @param childTagName 要查找的子节点标签名（区分大小写）
     * @return 符合条件的直接子节点列表，若没有匹配项则返回空列表（永远不为null）
     * 
     *  // 获取<ELEMENTS>下所有<ELEMENT>直接子节点
     *  List<Element> elements = XmlParseComm.getChildElementsByTagNames(elementsNode, "ELEMENTS", "ELEMENT");
     *
     *  // 遍历处理每个子节点（无需关心其内部结构）
     *  for (Element element : elements) {
     *      // 处理每个ELEMENT节点...
     *      String id = XmlParseComm.getDirectNodeValue(element, "ID");
     *      String name = XmlParseComm.getDirectNodeValue(element, "NAME");
     *  }
     */
    public static List<Element> getChildElementsByTagNames(Element parentNode, String parentTagName, String childTagName) {
        List<Element> childElements = new ArrayList<>();

        // 校验父节点是否为null
        if (parentNode == null) {
        	logEx("父节点为null，无法获取子节点");
            return childElements;
        }

        // 校验父节点标签名是否匹配（可选，但能提前发现错误）
        if (parentTagName != null && !parentTagName.isEmpty() 
                && !parentTagName.equals(parentNode.getTagName())) {
        	logEx("警告：父节点实际标签名[" + parentNode.getTagName() + "]与预期[" + parentTagName + "]不匹配");
        }

        // 校验子节点标签名是否有效
        if (childTagName == null || childTagName.trim().isEmpty()) {
        	logEx("子节点标签名不能为空");
            return childElements;
        }
        String trimmedChildTagName = childTagName.trim();

        // 获取并筛选直接子节点
        NodeList childNodes = parentNode.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node node = childNodes.item(i);
            // 只处理元素节点且标签名匹配的直接子节点
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element childElement = (Element) node;
                if (trimmedChildTagName.equals(childElement.getTagName())) {
                    childElements.add(childElement);
                }
            }
        }

        logEx("在[" + parentNode.getTagName() + "]节点下找到 " + childElements.size() + " 个[" + trimmedChildTagName + "]直接子节点");
        return childElements;
    }
    
    /**
     * 提取NETWORK-MASK元素中的xsi:nil属性信息并打印
     * @param networkMaskElement NETWORK-MASK标签对应的Element对象
     */
    public static final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
    public static String parseXsiNil(Element element) {
        if (element == null) {
            logEx("parseXsiNil: 输入的element元素为null");
            return null;
        }
        
        // 获取xsi:nil属性值（通过命名空间URI和属性本地名）
        String nilValue = element.getAttributeNS(XSI_NAMESPACE_URI, "nil");
        
        // 打印属性信息
        logEx("NETWORK-MASK标签的xsi:nil属性值: " + nilValue);
        
        // 打印是否为nil的判断结果
        boolean isNil = "true".equals(nilValue);
        logEx("NETWORK-MASK是否为nil: " + isNil);
        
        return nilValue;
    }
    
    /**
     * 根据属性名获取XML元素的属性值
     * @param element 目标XML元素（如IPV-4-CONFIGURATION、ETHERNET-PHYSICAL-CHANNEL）
     * @param attrName 要获取的属性名（如"S"、"UUID"）
     * @return 属性值（若元素为null/属性不存在，返回空字符串）
     */
    public static String getElementAttrValue(Element element, String attrName) {
        // 防御：元素为null时返回空
        if (element == null) {
            logEx("getElementAttrValue：传入的Element为null");
            return "";
        }
        // 防御：属性名为null/空时返回空
        if (attrName == null || attrName.trim().isEmpty()) {
            logEx("getElementAttrValue：传入的属性名（attrName）为空");
            return "";
        }
        // 获取属性值（属性不存在时返回空字符串）
        String attrValue = element.getAttribute(attrName);
        logEx("获取元素<" + element.getTagName() + ">的属性\"" + attrName + "\": " + attrValue);
        return attrValue;
    }
}
